/* 
    基于ts
    要求：实现 Promisify<T> 工具类型，其接受一个 Class，
    并将该 Class 的所有同步的实例方法，转换为异步的实例方法；
 */

/* 总结：
   使用TypeScript实现一个Promisify工具类型
   该类型将指定类的所有同步实例方法转换为异步方法
   主要思路是通过遍历类的属性，检查属性是否为函数，如果是函数则将其转换为异步方法
   否则保持不变，转换后的异步方法会返回 Promise对象，
   这样可以在使用时使用 async/await 语法来处理异步操作。
   将已有的同步代码转换为异步代码，满足异步编程的需求
*/

// 定义 Promisify工具类
type Promisify<T> = {
    // 遍历类型的每个属性
    // 如果属性方法是同步方法,则转化为Promise异步方法
    // 如果属性不是方法，则直接返回
    [k in keyof T]: T[k] extends (...args: infer P) => infer R ? (...args: P) => Promise<R> : T[k];
}
// 示例类 Foo
class Foo{
    foo(): string{
        return 'foo';
    }
    async bar(): Promise<string>{
        return Promise.resolve('bar');
    }
}
// 转换函数
const convertFoo = function (foo: Foo): Promisify<Foo>{
    // 创建一个新对象来存储转换后的异步方法
    const asyncFoo: Promisify<Foo> = {} as Promisify<Foo>;
    // 遍历原始对象的属性
    for (const key in foo) {
        // 判断属性是否为方法
        if (typeof foo[key] === 'function') {
            // 转成异步方法
            asyncFoo[key] = async function (...args: any[]) {
                const result = (foo[key] as any)(...args);
                if (result instanceof Promise) {
                    // 如果返回是promise的话直接返回
                    return await result;
                } else {
                    // 直接返回结果
                    return result;
                }
            }
        } else {
            // 不是方法
            asyncFoo[key] = foo[key];
        }
    }
    return asyncFoo;
}
async function main() {
    const f = new Foo();
    const asyncFoo = convertFoo(f);
    // 使用异步方法
    const foo = await asyncFoo.foo();
    console.log(foo);

    const bar = await asyncFoo.bar();
    console.log(bar);
}
main();